home *** CD-ROM | disk | FTP | other *** search
/ CICA 1993 April / CICA MS Windows - April 1993.iso / unzipped / programr / makemdi2 / chart.c < prev    next >
C/C++ Source or Header  |  1992-11-25  |  16KB  |  539 lines

  1. #define _CHART_C
  2. //----------------------------------------------------------------- 
  3. // CHART.C - Chart window management. 
  4. // 
  5. // MAKEMDI adaptation of Windows 3.1 SDK MAKEAPP system. 
  6. // 
  7. // MDI application design based on Chapter 7 of     
  8. // "Windows 3: A Developer's Guide" by Jeffrey Richter. 
  9. // 
  10. // Adaptation developed with permission of the author by  
  11. // John F. Holliday, Technisoft Corporation 
  12. // Telephone: (515) 472-9803, CompuServe: 71271,634 
  13. //
  14. // [DMM]    25-Nov-1992: Fixed crashing on exit
  15. //            Also tabified file to tabsize of 4
  16. //
  17. //            David M. Miller, Business Visions, Inc.
  18. //            Telephone: (212) 747-6118
  19. //            CompuServe: 72676,327
  20. //            internet: dmiller@hera.sbi.com
  21. //----------------------------------------------------------------- 
  22. #include "makemdi.h"
  23.  
  24.  
  25.  
  26. BOOL            Chart_Initialize(APP * papp)
  27. //----------------------------------------------------------------- 
  28. // Initialize all MDI child window classes. 
  29. //----------------------------------------------------------------- 
  30. {
  31.     WNDCLASS        cls;
  32.  
  33.     cls.hCursor = LoadCursor(NULL, IDC_ARROW);
  34.     cls.hIcon = NULL;
  35.     cls.lpszMenuName = NULL;
  36.     cls.hInstance = papp->hinst;
  37.     cls.lpszClassName = CLASS_CHART;
  38.     cls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  39.     cls.lpfnWndProc = Chart_WndProc;
  40.     cls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  41.     cls.cbWndExtra = sizeof(CHART*);
  42.     cls.cbClsExtra = 0;
  43.  
  44.     if (!RegisterClass(&cls))
  45.         return FALSE;
  46.  
  47.     return TRUE;
  48. }
  49.  
  50.  
  51.  
  52. void            Chart_Terminate(APP * papp)
  53. {
  54. }
  55.  
  56.  
  57.  
  58.  
  59. LRESULT CALLBACK _export Chart_WndProc(HWND hWnd,
  60.                                        UINT msg,
  61.                                        WPARAM wParam,
  62.                                        LPARAM lParam)
  63. {
  64.     CHART    *pchart = Chart_GetPtr(hWnd);
  65.  
  66.     if (pchart == NULL) {
  67.         if (msg == WM_NCCREATE) {
  68.             pchart = (CHART *) LocalAlloc(LPTR, sizeof(CHART));
  69.  
  70.             if (pchart == NULL)
  71.                 return 0L;
  72.  
  73.             pchart->hWnd = hWnd;
  74.             Chart_SetPtr(hWnd, pchart);
  75.         }
  76.         else {
  77.             return Chart_DefProc(hWnd, msg, wParam, lParam);
  78.         }
  79.     }
  80.  
  81.  
  82.     if (msg == WM_NCDESTROY) {
  83.         // DWORD result = HANDLE_MSG(hWnd, WM_NCDESTROY, Chart_OnNCDestroy); 
  84.  
  85.         if (pchart->hMenu != NULL)
  86.             DestroyMenu(pchart->hMenu);
  87.  
  88.         LocalFree((HLOCAL) OFFSETOF(pchart));
  89.         pchart = NULL;
  90.         Chart_SetPtr(hWnd, NULL);
  91.  
  92.         // return result; 
  93.     }
  94.  
  95.  
  96.     switch (msg) {
  97.         HANDLE_MSG(pchart, WM_CREATE, Chart_OnCreate);
  98.         HANDLE_MSG(pchart, WM_MDIACTIVATE, Chart_OnMdiActivate);
  99.         HANDLE_MSG(pchart, WM_MOUSEACTIVATE, Chart_OnMouseActivate);
  100.         HANDLE_MSG(pchart, WM_ENTERIDLE, Chart_OnEnterIdle);
  101.         HANDLE_MSG(pchart, WM_MENUSELECT, Chart_OnMenuSelect);
  102.         HANDLE_MSG(pchart, WM_SETCURSOR, Chart_OnSetCursor);
  103.         HANDLE_MSG(pchart, WM_LBUTTONDOWN, Chart_OnLButtonDown);
  104.         HANDLE_MSG(pchart, WM_CLOSE, Chart_OnClose);
  105.         HANDLE_MSG(pchart, WM_DESTROY, Chart_OnDestroy);
  106.         HANDLE_MSG(pchart, WM_PAINT, Chart_OnPaint);
  107.         HANDLE_MSG(pchart, WM_ERASEBKGND, Chart_OnEraseBkgnd);
  108.         HANDLE_MSG(pchart, WM_QUERYENDSESSION, Chart_OnQueryEndSession);
  109.         HANDLE_MSG(pchart, WM_ENDSESSION, Chart_OnEndSession);
  110.         HANDLE_MSG(pchart, WM_COMMAND, Chart_OnCommand);
  111.  
  112.         // Application messages. 
  113.  
  114.         HANDLE_MSG(pchart, AC_PAINTSTATBAR, Chart_OnPaintStatBar);
  115.         HANDLE_MSG(pchart, AW_PAINTMENUHELP, Chart_OnPaintMenuHelp);
  116.  
  117.     default:
  118.         return Chart_DefProc(hWnd, msg, wParam, lParam);
  119.     }
  120. }
  121.  
  122.  
  123.  
  124. typedef struct {
  125.     LPCSTR            lpszText;
  126.     COLORREF        clrText;
  127. }                CHART_INIT;
  128.  
  129.  
  130.  
  131.  
  132. HWND            Chart_CreateWindow(HWND hWndParent, int x, int y, int cx, int cy, BOOL fVisible, COLORREF clrText, LPCSTR lpszText)
  133. {
  134.     CHART_INIT        init;
  135.  
  136.     init.lpszText = lpszText;
  137.     init.clrText = clrText;
  138.  
  139.     return CreateWindowEx(
  140.                              0L,        // extendedStyle 
  141.                              CLASS_CHART,        // class name 
  142.                              NULL,        // text 
  143.                              (fVisible ? (WS_CHILD | WS_VISIBLE) : WS_CHILD),
  144.                              x, y, cx, cy,        // x, y, cx, cy 
  145.                              hWndParent,// hWndParent 
  146.                              NULL,        // hmenu 
  147.                              g_app.hinst,        // hInstance 
  148.                              &init);    // lpCreateParams 
  149. }
  150.  
  151.  
  152.  
  153.  
  154. BOOL            Chart_OnCreate(CHART * pchart, CREATESTRUCT FAR * lpCreateStruct)
  155. {
  156.     CHART_INIT FAR *pinit = (CHART_INIT FAR *) lpCreateStruct->lpCreateParams;
  157.  
  158.     pchart->lpszText = pinit->lpszText;
  159.     pchart->clrText = pinit->clrText;
  160.  
  161.     // If this window is first instance created of this class. 
  162.  
  163.     if (pchart->hMenu == NULL) {
  164.         // Initialize the menu and accelerator handles for this class. 
  165.  
  166.         pchart->hMenu = LoadMenu(g_app.hinst, MAKEINTRESOURCE(IDR_CHARTMENU));
  167.         pchart->hAccelTable = LoadAccelerators(g_app.hinst, MAKEINTRESOURCE(IDR_CHARTACCEL));
  168.     }
  169.  
  170.     return TRUE;
  171. }
  172.  
  173.  
  174.  
  175. void            Chart_OnMdiActivate(CHART * pchart, BOOL fBeingActivated, HWND hWndChild, HWND hWndPrevChild)
  176. {
  177.     if (fBeingActivated) {
  178.         // Child is being activated. 
  179.  
  180.         pchart->hWndPrevChild = hWndPrevChild;
  181.  
  182.         // If this child is being activated and no other child exists, 
  183.         // pretend that this child was the last activated child. 
  184.  
  185.         if (pchart->hWndPrevChild == NULL)
  186.             pchart->hWndPrevChild = pchart->hWnd;
  187.  
  188.         // Set the menu bar and the accelerators to the appropriate ones 
  189.         // for this window class. 
  190.  
  191.         Frame_ChangeMDIMenu(
  192.                                GETFRAME(pchart->hWnd),
  193.                                GetParent(pchart->hWnd),
  194.                                pchart->hMenu,
  195.                                CMD_WINDOWTILEVERT);
  196.  
  197.         g_app.hAccelTable = pchart->hAccelTable;
  198.  
  199.         // For the Status bar at the bottom of the Frame window to be  
  200.         // updated for this child's information. 
  201.  
  202.         InvalidateRect(GETFRAME(pchart->hWnd), NULL, TRUE);
  203.     }
  204.     else {
  205.         // Child is being deactivated. 
  206.         // Reset the previous child so WM_MOUSEACTIVATE will work Ok. 
  207.  
  208.         pchart->hWndPrevChild = NULL;
  209.     }
  210. }
  211.  
  212.  
  213.  
  214.  
  215. int                Chart_OnMouseActivate(CHART * pchart, HWND hWndTopLevel, UINT codeHitTest, UINT msg)
  216. //----------------------------------------------------------------- 
  217. // User clicked the mouse of the Child window. 
  218. // If the mouse is clicked in the window's client area and    
  219. // the previously active child was NOT this child, the 
  220. // mouse message should be eaten. 
  221. //----------------------------------------------------------------- 
  222. {
  223.     if ((codeHitTest == HTCLIENT) &&
  224.             (pchart->hWnd != pchart->hWndPrevChild))
  225.         return MA_ACTIVATEANDEAT;
  226.  
  227.     return MA_ACTIVATE;
  228. }
  229.  
  230.  
  231.  
  232. void            Chart_OnEnterIdle(CHART * pchart, UINT source, HWND hWndSource)
  233. //----------------------------------------------------------------- 
  234. // User stopped moving around in the help system, make the Frame 
  235. // believe that it received this message directly. 
  236. //----------------------------------------------------------------- 
  237. {
  238.     FORWARD_WM_ENTERIDLE(GETFRAME(pchart->hWnd), source, hWndSource, SendMessage);
  239. }
  240.  
  241.  
  242.  
  243. void            Chart_OnMenuSelect(CHART * pchart, HMENU hMenu, int item, HMENU hMenuPopup, UINT flags)
  244. //----------------------------------------------------------------- 
  245. // Normally, only MDI Child system menu options could appear 
  246. // in this message.     But the Frame window forces WM_MENUSELECT 
  247. // messages to appear here whenever a menu selection occurs. 
  248. //----------------------------------------------------------------- 
  249. {
  250.     WORD            wTemp;
  251.     HMENU            hMenuFrame;
  252.  
  253.     if (flags == -1 && (hMenu == (HMENU) 0)) {
  254.         // User has stopped using the menu system.    Notify Frame window 
  255.         // so that the status bar will be invalidated. 
  256.  
  257.         SendMessage(GETFRAME(pchart->hWnd), FW_SETMENUHELP, 0, 0);
  258.         return;
  259.     }
  260.  
  261.     switch (flags & (MF_POPUP | MF_SYSMENU)) {
  262.     case 0:
  263.         // Item is a menu item ID NOT on the Child's system menu. 
  264.         // If item is any of the MDI Children listed in the     
  265.         // "Window" menu, display the same help text. 
  266.  
  267.         if ((item > CMD_WINDOWCHILD) && (item <= CMD_WINDOWCHILD + 9))
  268.             item = CMD_WINDOWCHILD;
  269.  
  270.         wTemp = IDS_CHARTMENUID + item;
  271.         break;
  272.  
  273.     case MF_POPUP:
  274.         // Calculate the index of the top-level menu. 
  275.  
  276.         hMenuFrame = GetMenu(GETFRAME(pchart->hWnd));
  277.         wTemp = GetMenuItemCount(hMenuFrame);
  278.  
  279.         while (wTemp--)
  280.             if (GetSubMenu(hMenuFrame, wTemp) == hMenuPopup)
  281.                 break;
  282.  
  283.         wTemp += IDS_CHARTPOPUPID;
  284.  
  285.         if (!IsZoomed(pchart->hWnd))
  286.             wTemp++;
  287.         break;
  288.  
  289.     case MF_SYSMENU:
  290.         // Item is menu item ID from MDI Child's system menu. 
  291.  
  292.         wTemp = IDS_CHARTMENUID + ((item & 0x0FFF) >> 4);
  293.         break;
  294.  
  295.     case MF_POPUP | MF_SYSMENU:
  296.         // Item is handle to MDI Child's sys menu. 
  297.  
  298.         wTemp = IDS_CHARTPOPUPID;
  299.         break;
  300.     }
  301.  
  302.     // Tell the Frame that this window should display the help 
  303.     // text and the identifier for the help text. 
  304.  
  305.     SendMessage(GETFRAME(pchart->hWnd), FW_SETMENUHELP,
  306.                 (WPARAM) pchart->hWnd, (LPARAM) wTemp);
  307. }
  308.  
  309.  
  310.  
  311.  
  312. BOOL            Chart_OnSetCursor(CHART * pchart, HWND hWndCursor, UINT codeHitTest, UINT msg)
  313. //----------------------------------------------------------------- 
  314. // After an MDI Child becomes active, set the previously active 
  315. // child to this window so that mouse messages will NOT be eaten. 
  316. //----------------------------------------------------------------- 
  317. {
  318.     pchart->hWndPrevChild = pchart->hWnd;
  319.     return FORWARD_WM_SETCURSOR(pchart->hWnd, hWndCursor, codeHitTest, msg, Chart_DefProc);
  320. }
  321.  
  322.  
  323.  
  324. void            Chart_OnLButtonDown(CHART * pchart, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  325. //----------------------------------------------------------------- 
  326. // Just to let you know when the WM_LBUTTONDOWN message is received. 
  327. //----------------------------------------------------------------- 
  328. {
  329.     MessageBox(pchart->hWnd, "WM_LBUTTONDOWN", "Chart", MB_OK);
  330. }
  331.  
  332.  
  333.  
  334. void            Chart_OnClose(CHART * pchart)
  335. //----------------------------------------------------------------- 
  336. // Make sure that it is OK to close this child window. 
  337. //----------------------------------------------------------------- 
  338. {
  339.     if ((BOOL) SendMessage(pchart->hWnd, WM_QUERYENDSESSION, 0, 0)) {
  340.         SendMessage(pchart->hWnd, WM_ENDSESSION, TRUE, 0);
  341.         FORWARD_WM_CLOSE(pchart->hWnd, Chart_DefProc);
  342.     }
  343. }
  344.  
  345.  
  346.  
  347.  
  348. void            Chart_OnDestroy(CHART * pchart)
  349. //----------------------------------------------------------------- 
  350. // Notify the Frame window that a child has been destroyed after  
  351. // the child is actually destroyed.     (That's why we use 
  352. // PostMessage instead of SendMessage here). 
  353. //----------------------------------------------------------------- 
  354. {
  355.     PostMessage(GETFRAME(pchart->hWnd), FW_MDICHILDDESTROY, (WPARAM) pchart->hWnd, 0);
  356.     FORWARD_WM_DESTROY(pchart->hWnd, Chart_DefProc);
  357. }
  358.  
  359.  
  360.  
  361.  
  362. void            Chart_OnPaint(CHART * pchart)
  363. //----------------------------------------------------------------- 
  364. //----------------------------------------------------------------- 
  365. {
  366.     PAINTSTRUCT        ps;
  367.     HDC                hdc;
  368.     RECT            rc;
  369.  
  370.     hdc = BeginPaint(pchart->hWnd, &ps);
  371.  
  372.     GetClientRect(pchart->hWnd, &rc);
  373.     FillRect(hdc, &rc, GetStockBrush(WHITE_BRUSH));
  374.     InflateRect(&rc, -4, -4);
  375.     FrameRect(hdc, &rc, GetStockBrush(BLACK_BRUSH));
  376.  
  377.     if (pchart->lpszText) {
  378.         int                cch = lstrlen(pchart->lpszText);
  379.         int                x;
  380.         int                y;
  381.         SIZE            size;
  382.  
  383.         GetTextExtentPoint(hdc, pchart->lpszText, cch, &size);
  384.  
  385.         x = rc.left + (rc.right - rc.left - size.cx) / 2;
  386.         y = rc.top + (rc.bottom - rc.top - size.cy) / 2;
  387.  
  388.         SetTextColor(hdc, pchart->clrText);
  389.         TextOut(hdc, x, y, pchart->lpszText, cch);
  390.     }
  391.  
  392.     EndPaint(pchart->hWnd, &ps);
  393. }
  394.  
  395.  
  396.  
  397.  
  398.  
  399. BOOL            Chart_OnEraseBkgnd(CHART * pchart, HDC hdc)
  400. //----------------------------------------------------------------- 
  401. // Let DefWindowProc erase the background 
  402. //----------------------------------------------------------------- 
  403. {
  404.     return FORWARD_WM_ERASEBKGND(pchart->hWnd, hdc, DefWindowProc);
  405. }
  406.  
  407.  
  408.  
  409.  
  410. BOOL            Chart_OnQueryEndSession(CHART * pchart)
  411. //----------------------------------------------------------------- 
  412. //----------------------------------------------------------------- 
  413. {
  414.     WORD            wTemp;
  415.     BOOL            fOkToQuit = FALSE;
  416.  
  417.     // Prompt user whether to save changes to this document. 
  418.     // Usually, a dirty flag (stored in the window's extra bytes 
  419.     // is used to determine if it is necessary to ask this question). 
  420.  
  421.     // Construct string including the document's name. 
  422.  
  423.     lstrcpy(g_app.szBuf, "Save changes to ");
  424.     wTemp = lstrlen(g_app.szBuf);
  425.     GetWindowText(pchart->hWnd, g_app.szBuf + wTemp,
  426.                   sizeof(g_app.szBuf) - wTemp);
  427.     lstrcat(g_app.szBuf, "?");
  428.  
  429.     // Display message box to user.     The message box should     
  430.     // be system modal if the entire Windows session is being  
  431.     // terminated. (wParam is FALSE). 
  432.  
  433.     switch (
  434.                MessageBox(
  435.                              pchart->hWnd,
  436.                              g_app.szBuf,
  437.                              g_app.szName,
  438.                              MB_ICONQUESTION | MB_YESNOCANCEL |
  439.                              MB_APPLMODAL)) {
  440.     case IDYES:
  441.         // Save the document and it's OK to quit. 
  442.         fOkToQuit = TRUE;
  443.         break;
  444.  
  445.     case IDNO:
  446.         // Don't save the document and it's OK to quit. 
  447.         fOkToQuit = TRUE;
  448.         break;
  449.     }
  450.  
  451.     return fOkToQuit;
  452. }
  453.  
  454.  
  455.  
  456.  
  457.  
  458. void            Chart_OnEndSession(CHART * pchart, BOOL fEnding)
  459. //----------------------------------------------------------------- 
  460. // Do any last minute cleanup during this message. 
  461. //----------------------------------------------------------------- 
  462. {
  463. }
  464.  
  465.  
  466.  
  467.  
  468. void            Chart_OnCommand(CHART * pchart, int id, HWND hWndCtl, UINT codeNotify)
  469. //----------------------------------------------------------------- 
  470. // Any menu options NOT processed by the Frame are passed to the 
  471. // active child. 
  472. //----------------------------------------------------------------- 
  473. {
  474.     MessageBox(pchart->hWnd, "Option not implemented.", g_app.szName, MB_OK);
  475. }
  476.  
  477.  
  478.  
  479.  
  480. void            Chart_OnPaintStatBar(CHART * pchart, HDC hdc, LPPAINTSTRUCT psStatus)
  481. //----------------------------------------------------------------- 
  482. // Message sent by the Frame window when the status bar needs to  
  483. // be repainted. 
  484. //----------------------------------------------------------------- 
  485. {
  486.     // Construct status bar string for display. 
  487.  
  488.     LoadString(g_app.hinst, IDS_CHARTSTATUSBAR, g_app.szBuf, sizeof(g_app.szBuf));
  489.  
  490.     // Draw the horizontal dividing line separating the Status bar 
  491.     // from the MDICLIENT window. 
  492.  
  493.     psStatus->rcPaint.top += (int)
  494.             SendMessage(GETFRAME(pchart->hWnd), FW_DRAWSTATUSDIVIDE, 0,
  495.                         (LPARAM) psStatus);
  496.  
  497.     // Paint the text in the status bar. 
  498.  
  499.     TextOut(hdc, 0, psStatus->rcPaint.top, g_app.szBuf, lstrlen(g_app.szBuf));
  500. }
  501.  
  502.  
  503.  
  504.  
  505.  
  506. void            Chart_OnPaintMenuHelp(CHART * pchart, LPPAINTSTRUCT psStatus)
  507. //----------------------------------------------------------------- 
  508. // Message sent from Frame window to notify child that it should 
  509. // paint the status bar text for the last highlighted menu item. 
  510. // lParam = LPPAINTSTRUCT of Frame's status bar. 
  511. //----------------------------------------------------------------- 
  512. {
  513.     LRESULT            lResult;
  514.  
  515.     // Ask the Frame window what the last selected menu ID was. 
  516.     // This value was sent to the frame by this window during the  
  517.     // processing for the WM_MENUSELECT message. 
  518.  
  519.     lResult = SendMessage(GETFRAME(pchart->hWnd), FW_GETMENUHELP, 0, 0);
  520.  
  521.     // Draw the horizontal dividing line separating the Status bar 
  522.     // from the MDICLIENT window. 
  523.  
  524.     psStatus->rcPaint.top += (int)
  525.             SendMessage(GETFRAME(pchart->hWnd), FW_DRAWSTATUSDIVIDE, 0,
  526.                         (LPARAM) psStatus);
  527.  
  528.     // Construct the string that is to be displayed. 
  529.  
  530.     LoadString(g_app.hinst, LOWORD(lResult), g_app.szFmt, sizeof(g_app.szFmt));
  531.     GetWindowText(pchart->hWnd, g_app.szCap, sizeof(g_app.szCap));
  532.     wsprintf(g_app.szBuf, g_app.szFmt, (LPSTR) g_app.szCap);
  533.  
  534.     // Paint the menu help text in the status bar. 
  535.  
  536.     TextOut(psStatus->hdc,
  537.             0, psStatus->rcPaint.top, g_app.szBuf, lstrlen(g_app.szBuf));
  538. }
  539.